package com.sitech.ibnms.c3p.quartz;

import com.sitech.ibnms.c3p.Application;
import com.sitech.ibnms.c3p.domain.C3pExecNotice;
import com.sitech.ibnms.c3p.domain.C3pTask;
import com.sitech.ibnms.c3p.mappers.C3pExecNoticeMapper;
import com.sitech.ibnms.c3p.mappers.C3pTaskMapper;
import com.sitech.ibnms.c3p.task.listeners.TaskWarningListener;
import com.sitech.ibnms.c3p.util.JSONUtil;
import com.sitech.ismp.workflow.dao.ProcessInstanceDAO;
import com.sitech.ismp.workflow.domain.ProcessInstance;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.ignite.Ignite;
import org.apache.ignite.lang.IgniteRunnable;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

import static com.sitech.ibnms.c3p.Application.getBean;

/**
 * Created by liujhc on 9/28.
 * 任务检测 看任务执行超时  ，看整个任务 执行时长  如果 超过 正常时间 则提示
 */
public class C3pTaskWatchdogJob implements Job {

    private Logger logger = LoggerFactory.getLogger(C3pTaskWatchdogJob.class);

    @Autowired
    private Ignite ignite;

    @Override
    public void execute(final JobExecutionContext context) throws JobExecutionException {
        ignite.compute().run(new IgniteRunnable() {
            @Override
            public void run() {
                try {
                    C3pExecNoticeMapper noticeMapper = getBean(C3pExecNoticeMapper.class);
                    ProcessInstanceDAO processInstanceDAO = getBean(ProcessInstanceDAO.class);
                    C3pTaskMapper taskMapper = getBean(C3pTaskMapper.class);
                    Collection<TaskWarningListener> taskWarningListeners = Application.getContext().getBeansOfType(TaskWarningListener.class).values();
                    Date now = new Date();
                    Date previousFireTime = ObjectUtils.defaultIfNull(context.getPreviousFireTime(), DateUtils.addHours(now, -1));
                    // 执行超时提醒
                    List<C3pExecNotice> execNotices = noticeMapper.findByExecTimeout(previousFireTime);
                    // 启动超时提醒
                    execNotices.addAll(noticeMapper.findByFireDelay(previousFireTime.getTime(), context.getFireTime().getTime()));
                    Map<Integer, ProcessInstance> processInstanceCache = new HashMap<Integer, ProcessInstance>();
                    for (C3pExecNotice execNotice : execNotices) {
                        C3pTask c3pTask = taskMapper.findById(execNotice.getTaskId());
                        String noticeContent = getNoticeContent(c3pTask, execNotice);
                        execNotice.setNoticeContent(noticeContent);
                        logger.info("execNotice:{}", JSONUtil.toJSON(execNotice));
                        int serialNo = Integer.parseInt(execNotice.getExecId());
                        ProcessInstance processInstance = processInstanceCache.get(serialNo);
                        if (processInstance == null) {
                            try {
                                processInstance = processInstanceDAO.queryProcessInstanceInfoBySerialNo(serialNo);
                            } catch (Exception e) {
                                logger.error("Failed to queryProcessInstanceInfoBySerialNo(" + serialNo + ")", e);
                                processInstance = processInstanceDAO.queryProcessInstanceBySerialNo(serialNo);
                                // 删除脏数据
                                processInstanceDAO.deleteProcessInstanceBySerialNo(serialNo);
                            }
                            processInstanceCache.put(serialNo, processInstance);
                        }

                        for (TaskWarningListener taskListener : taskWarningListeners) {
                            try {
                                taskListener.onWarning(c3pTask, processInstance, execNotice);
                            } catch (Exception e) {
                                logger.error(ToStringBuilder.reflectionToString(execNotice), e);
                            }
                        }
                    }
                    if (!execNotices.isEmpty()) noticeMapper.insert(execNotices);
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }
            }
        });
    }

    private String getNoticeContent(C3pTask task, C3pExecNotice execNotice) {
        String pattern = "MM月dd日HH:mm:ss";
        Date execBeginTime = execNotice.getExecBeginTime();
        String beginTime = DateFormatUtils.format(execBeginTime, pattern);
        if (execNotice.getExecId() == null) {
            return String.format("任务“%s”超时未启动(阈值为%s秒)，应该启动的时间为%s",
                    task.getTaskName(), task.getDelayTime(), beginTime);
        } else {
            String endTime;
            if (execNotice.getExecuteTime() == -1) {
                endTime = "现在未完成";
            } else {
                Date execEndTime = DateUtils.addSeconds(execBeginTime, execNotice.getExecuteTime());
                endTime = DateFormatUtils.format(execEndTime, pattern);
            }
            return String.format("任务“%s”执行超时(阈值%s秒)，任务执行时间为%s至%s",
                    task.getTaskName(), task.getExecuteTime(), beginTime, endTime);
        }
    }
}